<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Mouse as a Paint-Brush</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d6/d00/tutorial_py_root.html">OpenCV-Python Tutorials</a></li><li class="navelem"><a class="el" href="../../dc/d4d/tutorial_py_table_of_contents_gui.html">Gui Features in OpenCV</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Mouse as a Paint-Brush </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<ul>
<li>Learn to handle mouse events in OpenCV</li>
<li>You will learn these functions : <b><a class="el" href="../../d7/dfc/group__highgui.html#ga89e7806b0a616f6f1d502bd8c183ad3e" title="Sets mouse handler for the specified window. ">cv.setMouseCallback()</a></b></li>
</ul>
<h2>Simple Demo </h2>
<p>Here, we create a simple application which draws a circle on an image wherever we double-click on it.</p>
<p>First we create a mouse callback function which is executed when a mouse event take place. Mouse event can be anything related to mouse like left-button down, left-button up, left-button double-click etc. It gives us the coordinates (x,y) for every mouse event. With this event and location, we can do whatever we like. To list all available events available, run the following code in Python terminal: </p><div class="fragment"><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line">events = [i <span class="keywordflow">for</span> i <span class="keywordflow">in</span> dir(cv) <span class="keywordflow">if</span> <span class="stringliteral">&#39;EVENT&#39;</span> <span class="keywordflow">in</span> i]</div><div class="line"><a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>( events )</div></div><!-- fragment --><p> Creating mouse callback function has a specific format which is same everywhere. It differs only in what the function does. So our mouse callback function does one thing, it draws a circle where we double-click. So see the code below. Code is self-explanatory from comments : </p><div class="fragment"><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"></div><div class="line"><span class="comment"># mouse callback function</span></div><div class="line"><span class="keyword">def </span>draw_circle(event,x,y,flags,param):</div><div class="line">    <span class="keywordflow">if</span> event == cv.EVENT_LBUTTONDBLCLK:</div><div class="line">        <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">cv.circle</a>(img,(x,y),100,(255,0,0),-1)</div><div class="line"></div><div class="line"><span class="comment"># Create a black image, a window and bind the function to window</span></div><div class="line">img = np.zeros((512,512,3), np.uint8)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">cv.namedWindow</a>(<span class="stringliteral">&#39;image&#39;</span>)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga89e7806b0a616f6f1d502bd8c183ad3e">cv.setMouseCallback</a>(<span class="stringliteral">&#39;image&#39;</span>,draw_circle)</div><div class="line"></div><div class="line">while(1):</div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&#39;image&#39;</span>,img)</div><div class="line">    <span class="keywordflow">if</span> <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>(20) &amp; 0xFF == 27:</div><div class="line">        <span class="keywordflow">break</span></div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga6b7fc1c1a8960438156912027b38f481">cv.destroyAllWindows</a>()</div></div><!-- fragment --> <h2>More Advanced Demo </h2>
<p>Now we go for a much better application. In this, we draw either rectangles or circles (depending on the mode we select) by dragging the mouse like we do in Paint application. So our mouse callback function has two parts, one to draw rectangle and other to draw the circles. This specific example will be really helpful in creating and understanding some interactive applications like object tracking, image segmentation etc. </p><div class="fragment"><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"></div><div class="line">drawing = <span class="keyword">False</span> <span class="comment"># true if mouse is pressed</span></div><div class="line">mode = <span class="keyword">True</span> <span class="comment"># if True, draw rectangle. Press &#39;m&#39; to toggle to curve</span></div><div class="line">ix,iy = -1,-1</div><div class="line"></div><div class="line"><span class="comment"># mouse callback function</span></div><div class="line"><span class="keyword">def </span>draw_circle(event,x,y,flags,param):</div><div class="line">    <span class="keyword">global</span> ix,iy,drawing,mode</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> event == cv.EVENT_LBUTTONDOWN:</div><div class="line">        drawing = <span class="keyword">True</span></div><div class="line">        ix,iy = x,y</div><div class="line"></div><div class="line">    <span class="keywordflow">elif</span> event == cv.EVENT_MOUSEMOVE:</div><div class="line">        <span class="keywordflow">if</span> drawing == <span class="keyword">True</span>:</div><div class="line">            <span class="keywordflow">if</span> mode == <span class="keyword">True</span>:</div><div class="line">                <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gac865734d137287c0afb7682ff7b3db23">cv.rectangle</a>(img,(ix,iy),(x,y),(0,255,0),-1)</div><div class="line">            <span class="keywordflow">else</span>:</div><div class="line">                <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">cv.circle</a>(img,(x,y),5,(0,0,255),-1)</div><div class="line"></div><div class="line">    <span class="keywordflow">elif</span> event == cv.EVENT_LBUTTONUP:</div><div class="line">        drawing = <span class="keyword">False</span></div><div class="line">        <span class="keywordflow">if</span> mode == <span class="keyword">True</span>:</div><div class="line">            <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gac865734d137287c0afb7682ff7b3db23">cv.rectangle</a>(img,(ix,iy),(x,y),(0,255,0),-1)</div><div class="line">        <span class="keywordflow">else</span>:</div><div class="line">            <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670">cv.circle</a>(img,(x,y),5,(0,0,255),-1)</div></div><!-- fragment --><p> Next we have to bind this mouse callback function to OpenCV window. In the main loop, we should set a keyboard binding for key 'm' to toggle between rectangle and circle. </p><div class="fragment"><div class="line">img = np.zeros((512,512,3), np.uint8)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">cv.namedWindow</a>(<span class="stringliteral">&#39;image&#39;</span>)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga89e7806b0a616f6f1d502bd8c183ad3e">cv.setMouseCallback</a>(<span class="stringliteral">&#39;image&#39;</span>,draw_circle)</div><div class="line"></div><div class="line">while(1):</div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&#39;image&#39;</span>,img)</div><div class="line">    k = <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>(1) &amp; 0xFF</div><div class="line">    <span class="keywordflow">if</span> k == ord(<span class="stringliteral">&#39;m&#39;</span>):</div><div class="line">        mode = <span class="keywordflow">not</span> mode</div><div class="line">    <span class="keywordflow">elif</span> k == 27:</div><div class="line">        <span class="keywordflow">break</span></div><div class="line"></div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga6b7fc1c1a8960438156912027b38f481">cv.destroyAllWindows</a>()</div></div><!-- fragment --> <h2>Additional Resources </h2>
<h2>Exercises </h2>
<ol type="1">
<li>In our last example, we drew filled rectangle. You modify the code to draw an unfilled rectangle. </li>
</ol>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
